use honeybee::mongodb;
use honeybee::mongodb::bson;
use honeybee::prelude::*;
use honeybee::Result;
use umsg_db::UmsgType;

use super::User;

impl User {
    pub async fn login_process_umsgs(&mut self) -> Result<()> {
        let msgs = umsg_db::list_no_ack_messages(self.uid).await?;
        for msg in msgs {
            if let Err(err) = self
                .handle_umsg(&msg._id.to_hex(), msg.msg_type, &msg.msg)
                .await
            {
                error!(
                    "{} login process umsg object_id:{} msg_type:{:?} msg:{} err:{}",
                    self, msg._id, msg.msg_type, msg.msg, err
                );
            }
        }
        Ok(())
    }

    async fn handle_umsg(
        &mut self,
        object_id: &str,
        msg_type: UmsgType,
        msg_doc: &mongodb::bson::Document,
    ) -> Result<()> {
        info!(
            "{} handle umsg object_id:{} msg_type:{:?} msg:{}",
            self, object_id, msg_type, msg_doc
        );
        umsg_db::ack_message(self.uid, object_id).await?;
        match msg_type {
            UmsgType::UmsgTest => {
                if let Err(err) = self.handle_umsg_test(bson::from_document(msg_doc.clone())?) {
                    error!(
                        "{} handle umsg object_id:{} type:{:?} msg:{} err:{}",
                        self, object_id, msg_type, msg_doc, err,
                    );
                }
            }
        }
        Ok(())
    }

    fn handle_umsg_test(&mut self, msg: umsg_db::UmsgTest) -> Result<()> {
        info!("{} handle umsg:{:?} success", self, msg);
        Ok(())
    }
}

#[async_trait::async_trait]
impl Handler<proto::NewUmsgNotify> for User {
    async fn handle(&mut self, _ctx: &mut Context<Self>, msg: proto::NewUmsgNotify) -> Result<()> {
        let msg_doc = bson::Document::from_reader(&mut msg.msg_bytes.as_slice())?;
        if let Err(err) = self
            .handle_umsg(&msg.object_id, msg.msg_type, &msg_doc)
            .await
        {
            error!(
                "{} process umsg object_id:{} type:{:?} msg:{} error:{}",
                self, msg.object_id, msg.msg_type, msg_doc, err
            )
        }
        Ok(())
    }
}
